#include "misc/fs_ext.hpp"
#include "misc/string_ext.hpp"

#include <cstdlib>
#include <cstring>

#include <sys/stat.h>
#include <unistd.h>

using std::string;

static bool
is_file_exist0(const char *path) {
    struct stat buffer;
    return (::stat(path, &buffer) == 0);
}

bool
is_file_exist(std::string &path, bool case_insensitive) {
    if (is_file_exist0(path.c_str())) {
        return true;
    }
    std::string lpath = to_lower_string(path);
    if (case_insensitive && is_file_exist0(lpath.c_str())) {
        path = std::move(lpath);
        return true;
    }
    return false;
}

string
get_current_dir() {
    char *cs = ::getcwd(NULL, 0);
    string s(cs);
    ::free(cs);
    return std::move(s);
}

string
resolve_path(const std::string &path) {
    if (!path.empty()) {
        if (path[0] == '/') {
            return path;
        } else {
            char *cs = ::realpath(path.c_str(), NULL);
            if (cs) {
                string s(cs);
                ::free(cs);
                return std::move(s);
            }
        }
    }
    return string();
}

string
join_path(const string &a, const string &b) {
    string s;
    s.reserve(a.size() + b.size() + 1);
    if (!a.empty()) {
        // a remains only one '/' on tail
        auto aend = a.cend();
        while (*(aend - 1) == '/') aend--;
        if (aend != a.cend()) {
            s.append(a.cbegin(), aend + 1);
        } else {
            s.append(a.cbegin(), aend).append("/");
        }
    }
    if (!b.empty()) {
        // b removes all '/' on head and tail
        auto bbegin = b.cbegin();
        while (*(bbegin) == '/') bbegin++;
        auto bend = b.cend();
        while (*(bend - 1) == '/') bend--;
        s.append(bbegin, bend);
    }
    return std::move(s);
}

bool
is_filename(const string &path) {
    return path.rfind('/') == string::npos;
}

string
get_filename(const string &path) {
    auto pos = path.rfind('/');
    if (pos == string::npos) {
        return path;
    }
    return path.substr(pos + 1);
}

string
get_basename(const string &path) {
    auto pos1 = path.rfind('/');
    pos1 = (pos1 == string::npos) ? 0 : pos1 + 1;
    auto pos2 = path.rfind('.');
    if (pos2 < pos1) pos2 = string::npos;
    return path.substr(pos1, pos2);
}
